<template>
  <div class="k-scroll" ref="scroll" @touchmove='touchMove' @touchend="touchEnd" @scroll="scroll" :style="{'scroll-behavior':useSmooth?'smooth':'auto'}">
    <!-- 顶部容器 -->
    <div v-if="topType==='update'" class="top-update"
      :style="{height:topHeight+'px',transitionDuration:duration +'ms',backgroundColor:topColor,fontSize:fontSize,color:fontColor}">
      <div v-if="!isRefresh && !updateComplete" class="before">
        <img :class="{arrow:true,rotate:topHeight>=updateThreshold}" :style="{height:imageSize,width:imageSize}"
          src="@/assets/img/icons/arrow.svg">
        <div v-if="topHeight<updateThreshold">下拉可以刷新</div>
        <div v-if="topHeight>=updateThreshold">释放立即刷新</div>
      </div>
      <div v-if="isRefresh" class="running">
        <van-loading class="load-ico" type="circular" :size="imageSize"></van-loading>
        <div>{{updatingText}}</div>
      </div>
      <div v-if="updateComplete" class="complete">{{updateCompleteText}}</div>
    </div>
    <div v-if="topType==='stretch'" class="top-stretch"
      :style="{height:topHeight+'px',transitionDuration:duration +'ms',backgroundColor:topColor}"></div>
    <slot></slot>
    <!-- 底部容器 -->
    <div v-if="bottomType==='load'" class="bottom-load"
      :style="{height:isnomore?'40px':bottomHeight+'px',transitionDuration:duration +'ms',backgroundColor:bottomColor,fontSize:fontSize,color:fontColor}">
      <van-loading v-if="!isnomore && isLoading" class="load-ico" type="circular" :size="imageSize"></van-loading>
      <div v-if="!isnomore && isLoading">{{loadingText}}</div>
      <div v-if="!isnomore && !isLoading">{{loadCompleteText}}</div>
      <div v-if="isnomore" class="nomore">
        <div class="line"></div>
        <span>{{nomoreText}}</span>
        <div class="line"></div>
      </div>
    </div>
    <div v-if="bottomType==='stretch'" class="bottom-stretch"
      :style="{height:bottomHeight+'px',transitionDuration:duration +'ms',backgroundColor:bottomColor}">
    </div>
  </div>
</template>

<script>
  export default {
    name: 'k-scroll',
    data() {
      return {
        //顶部高度
        topHeight: 0,
        //底部高度
        bottomHeight: 0,
        //记录按下位置
        touchY: 0,
        //过渡时间
        duration: 0,
        //是否刷新完成
        updateComplete: false,
        //是否已发送触底事件
        touchBottom: false
      }
    },
    watch: {
      isRefresh(value) {
        //刷新结束
        if (!value) {
          this.updateComplete = true //显示刷新结果
          //展示刷新结果后，回弹顶部拉伸
          setTimeout(() => {
            this.duration = this.transitionDuration
            this.topHeight = 0
            //等待回弹结束后重置变量
            setTimeout(() => {
              this.updateComplete = false
            }, this.transitionDuration)
          }, this.stopTime)
        }
      },
      isLoading(value) {
        //加载结束
        if (!value) {
          //展示加载结果后，回弹底部拉伸
          setTimeout(() => {
            this.duration = this.transitionDuration
            this.bottomHeight = 0
            //等待回弹结束后重置变量
            setTimeout(() => {
              this.touchBottom = false
            }, this.transitionDuration)
          }, this.stopTime)

        }
      }
    },
    methods: {
      //手指滑动事件
      touchMove(e) {
        if (this.updateComplete || this.isRefresh || this.isLoading) return //正在刷新中或刚刚刷新完成不进行拉伸
        this.duration = 0 //归零过渡动画时间
        //滚动到达顶部时，进行拉伸计算
        if (this.$refs.scroll.scrollTop == 0) {
          if (this.touchY == 0) this.touchY = e.touches[0].clientY
          this.topHeight = (e.touches[0].clientY - this.touchY) * (0.5 - (e.touches[0].clientY - this.touchY) / 2000)
        }
        //到达底部时进行底部拉伸计算
        else if (Math.abs(this.$refs.scroll.scrollTop + this.$refs.scroll.clientHeight - this.$refs.scroll
            .scrollHeight) <
          2) {
          if (this.bottomType == 'stretch') {
            if (this.touchY == 0) this.touchY = e.touches[0].clientY
            this.bottomHeight = (this.touchY - e.touches[0].clientY) * (0.5 - (this.touchY - e.touches[0].clientY) /
              2000)
            //跟随滚动到底部
            this.$refs.scroll.scrollTop = this.$refs.scroll.scrollHeight
          }
        }
      },
      //手指抬起事件
      touchEnd() {
        this.touchY = 0 //重置按下Y坐标
        this.duration = this.transitionDuration //设置回弹过渡时间
        // 正在刷新中或刚刚刷新完成不进行事件处理
        if (this.updateComplete || this.isRefresh || this.isLoading) return
        //顶部刷新处理
        if (this.topType == 'update') {
          if (this.topHeight >= this.updateThreshold) {
            this.topHeight = this.stop
            this.$emit('updating')
          } else {
            setTimeout(() => {
              this.topHeight = 0
            }, 10)
          }
          //顶部拉伸回弹
        } else if (this.topType == 'stretch') {
          setTimeout(() => {
            this.topHeight = 0
          }, 10)
        }
        //底部拉伸回弹
        if (this.bottomType == 'stretch') {
          setTimeout(() => {
            this.bottomHeight = 0
          }, 10)
        }
      },
      //滚动事件
      scroll() {
        this.$emit('scroll', this.$refs.scroll.scrollTop)
        //div滚动到底部
        if (Math.abs(this.$refs.scroll.scrollTop + this.$refs.scroll.clientHeight - this.$refs.scroll.scrollHeight) <
          this.loadThreshold + 2) {
          if (this.isRefresh) return //正在刷新中，直接返回
          if (this.isnomore) return //全部数据已经加载完毕，停止加载事件派发
          if (this.touchBottom) return // 已经发送触底事件，直接返回
          this.touchBottom = true
          //底部为加载类型，派发事件
          if (this.bottomType == 'load') {
            this.$emit('loading',true)
            this.duration = 0
            this.bottomHeight = 40
            //延时滚动到最底部
            // setTimeout(() => {
            //   this.$refs.scroll.scrollTop = this.$refs.scroll.scrollHeight
            // }, 10)
          }
        }
      },
      //滚动到指定位置
      scrollTo(e) {
        this.$refs.scroll.scrollTop = e
      }

    },
  //  //数据双向绑定v-model
  // model: {
  //   prop: 'isLoading',
  //   event: 'loading',
  // },
    props: {
      //是否正在刷新
      isRefresh: {
        type: Boolean,
        default: false,
      },
      //是否正在加载
      isLoading: {
        type: Boolean,
        default: false,
      },
      //顶部拉伸区域背景色
      topColor: {
        type: String,
        default: 'white'
      },
      //底部拉伸区域背景色
      bottomColor: {
        type: String,
        default: 'white'
      },
      //顶部类型,update刷新型,stretch拉伸型,none啥也没
      topType: {
        type: String,
        default: 'update'
      },
      //底部类型,load加载型,stretch拉伸型,none啥也没
      bottomType: {
        type: String,
        default: 'load'
      },
      //回弹过渡动画时间ms
      transitionDuration: {
        type: Number,
        default: 200
      },
      //顶部停留位置,单位px
      stop: {
        type: Number,
        default: 50
      },
      //顶部刷新阈值,单位px
      updateThreshold: {
        type: Number,
        default: 70
      },
      //底部刷新阈值,单位px
      loadThreshold: {
        type: Number,
        default: 0
      },
      //是否没有更多了
      isnomore: {
        type: Boolean,
        default: false
      },
      //刷新完成提示文字停留时间,单位ms
      stopTime: {
        type: Number,
        default: 500
      },
      //刷新完成提示文字
      updateCompleteText: {
        type: String,
        default: '刷新成功'
      },
      //没有更多显示文字
      nomoreText: {
        type: String,
        default: '没有更多了'
      },
      //加载完成提示文字
      loadCompleteText: {
        type: String,
        default: '加载完成'
      },
      //正在刷新中提示文字
      updatingText: {
        type: String,
        default: '正在刷新...'
      },
      //正在加载中提示文字
      loadingText: {
        type: String,
        default: '加载中...'
      },
      //提示文字大小
      fontSize: {
        type: String,
        default: '14px'
      },
      //提示文字颜色
      fontColor: {
        type: String,
        default: '#909497'
      },
      //图标大小,宽高一样
      imageSize: {
        type: String,
        default: '18px'
      },
      //是否开启平滑滚动
      useSmooth:{
        type:Boolean,
        default:false
      }
    }
  }
</script>

<style src="./scroll.css" scoped></style>
